<?php
/**
 * Created by zj.
 * User: zj
 * Date: 2019/11/11 0011
 * Time: 下午 3:27
 */
namespace com\rs\dns\service;

use com\rs\dns\constant\InstallConstant;
use com\rs\dns\controller\install\InstallForm;
use com\rs\dns\exception\BaException;
use restphp\utils\RestHttpRequestUtils;
use restphp\utils\RestStringUtils;

/**
 * Class CheckInstallUtils
 * @package php\utils.
 */
class InstallService {
    /**
     * 安装文件目录.
     * @var string
     */
    private static $_strInstallFilePath = "runtime/install/install.lock";

    /**
     * 安装配置目录.
     * @var string .
     */
    private static $_strInstallConfigFile = "runtime/install/install.config.php";

    /**
     * 安装相关页或接口访问路径前部分.
     * @var string
     */
    private static $_strDirUrl = "/install";

    public static function getInstallFilePath() {
        return ROOT_DIR . self::$_strInstallFilePath;
    }

    public static function getConfigFile() {
        return ROOT_DIR . self::$_strInstallConfigFile;
    }

    /**
     * 权限校验.
     */
    public static function run() {
        if (self::bIsInstall()) {
            return;
        }

        $strUri = RestHttpRequestUtils::getUri();
        if (RestStringUtils::startWith($strUri, self::$_strDirUrl) ||
            RestStringUtils::startWith($strUri, "/js/") ||
            RestStringUtils::startWith($strUri, "/css/") ||
            RestStringUtils::startWith($strUri, "/images/")) {
            return;
        }

        header("LOCATION: " . self::$_strDirUrl);
    }

    /**
     * 是否已安装配置.
     * @return bool.
     */
    public static function bIsInstall() {
        if (!file_exists(self::getInstallFilePath())) {
            return false;
        }

        $strContent = file_get_contents(self::getInstallFilePath());
        $dbInfo = isset($GLOBALS['_DB_SQL_SERVER']) ? $GLOBALS['_DB_SQL_SERVER'] : array(RestStringUtils::randomCode());
        $strCheckSource = md5(json_encode($dbInfo));
        if ($strContent != $strCheckSource) {
            return false;
        }
        return true;
    }

    /**
     * @param $strFile
     * @return false|string
     */
    private static function _getFileDir($strFile) {
        return substr($strFile, 0, strrpos($strFile, '/'));
    }

    /**
     * 安装锁目录是否有权限.
     * @return bool
     */
    public static function bInstallLockCanWrite() {
        $strTestCode = RestStringUtils::randomCode() . ":test_install";
        $lockFile = self::getInstallFilePath();
        $lockFileDir = self::_getFileDir($lockFile);
        if (!is_dir($lockFileDir . '/')) {
            try {
                mkdir($lockFileDir);
            } catch (\Exception $e) {
                return false;
            }
        }
        @file_put_contents($lockFile, $strTestCode);
        $strContent = @file_get_contents($lockFile);
        @unlink($lockFile);
        return $strTestCode == $strContent;
    }

    /**
     * 安装信息记录文件是否有权限.
     * @return bool
     */
    public static function bConfigCanWrite() {
        $installFormTest = new InstallForm();
        $installFormTest->setDbServer(RestStringUtils::randomCode(6));
        $installFormTest->setDbPort(RestStringUtils::randomCode(6));
        $installFormTest->setDbUsername(RestStringUtils::randomCode(6));
        $installFormTest->setDbPassword(RestStringUtils::randomCode(6));
        $installFormTest->setDbName(RestStringUtils::randomCode(6));
        $strTestCode = self::getInstallContent($installFormTest);
        $infoFile = self::getConfigFile();
        $infoFileDir = self::_getFileDir($infoFile);
        if (!is_dir($infoFileDir . '/')) {
            try {
                mkdir($infoFileDir);
            } catch (\Exception $e) {
                return false;
            }
        }
        @file_put_contents(self::getConfigFile(), $strTestCode);
        $strContent = @file_get_contents(self::getConfigFile());
        @unlink($infoFile);
        return $strTestCode == $strContent;
    }

    /**
     * 安装.
     * @param InstallForm $installForm
     * @throws BaException
     * @throws \restphp\exception\RestException
     */
    public static function install($installForm) {
        if (self::bIsInstall()) {
            throw new BaException(InstallConstant::INSTALL_ERROR_INSTALLED);
        }

        $arrDbConfig = array(
            'dbhost'	=> $installForm->getDbServer() . ',' . $installForm->getDbPort(),
            'dbuser'	=> $installForm->getDbUsername(),
            'dbpass'	=> $installForm->getDbPassword(),
            'dbname'	=> $installForm->getDbName(),
            'charset'	=> 'gb2312'
        );

        $GLOBALS['_DB_SQL_SERVER'] = array(
            'DB_PREFIX' => '', //表前缀
            'Def_Select'	=> $arrDbConfig,
            'Def_Update'	=> $arrDbConfig
        );

        //数据库安装检查
        InstallDbService::execute($installForm);

        //写入安装数据
        $strConfig = self::getInstallContent($installForm);
        @file_put_contents(self::getConfigFile(), $strConfig);
        $strContent = @file_get_contents(self::getConfigFile());
        if ($strConfig!=$strContent) {
            throw new BaException(InstallConstant::INSTALL_ERROR_WRITE_CONFIG);
        }

        //写安装保护锁
        $strCheckSource = md5(json_encode($GLOBALS['_DB_SQL_SERVER']));
        @file_put_contents(self::getInstallFilePath(), $strCheckSource);
        $strContentCheck = @file_get_contents(self::getInstallFilePath());
        if ($strCheckSource != $strContentCheck) {
            throw new BaException(InstallConstant::INSTALL_ERROR_WRITE_LOCK);
        }
    }

    /**
     * @param InstallForm $installForm
     * @return string
     */
    public static function getInstallContent($installForm) {
        $dbServer = $installForm->getDbServer();
        $dbPort = $installForm->getDbPort();
        $dbUsername = $installForm->getDbUsername();
        $dbPassword = $installForm->getDbPassword();
        $dbName = $installForm->getDbName();
        return "<?php return array(
        'DATABASE_SQL_SERVER' => array(
            'DB_PREFIX' => '',
            'Def_Select'	=> array(
                'dbhost'	=> '{$dbServer},{$dbPort}',
                'dbuser'	=> '{$dbUsername}',
                'dbpass'	=> '{$dbPassword}',
                'dbname'	=> '{$dbName}',
                'charset'	=> 'gb2312'
            ),
            'Def_Update'	=> array(
                'dbhost'	=> '{$dbServer},{$dbPort}',
                'dbuser'	=> '{$dbUsername}',
                'dbpass'	=> '{$dbPassword}',
                'dbname'	=> '{$dbName}',
                'charset'	=> 'gb2312'
            )
        ));";
    }
}